import re
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import json
import os
from tkinter.scrolledtext import ScrolledText
import subprocess


class LargeTextDialog(tk.Toplevel):
    """自定义大文本框对话框"""

    def __init__(self, parent, title="", prompt="", initial_value=""):
        super().__init__(parent)
        self.title(title)
        self.result = None

        self.transient(parent)
        self.grab_set()

        # 提示文本
        tk.Label(self, text=prompt, font=("Arial", 10)).pack(
            padx=10, pady=5, anchor="w")

        # 创建大文本框
        self.text_area = tk.Text(self, wrap=tk.WORD, font=("Arial", 10))
        self.text_area.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
        self.text_area.insert("1.0", initial_value)

        # 按钮区域
        btn_frame = tk.Frame(self)
        btn_frame.pack(padx=10, pady=10, fill=tk.X)

        tk.Button(btn_frame, text="确定", command=self.on_ok).pack(
            side=tk.RIGHT, padx=5)
        tk.Button(btn_frame, text="取消",
                  command=self.on_cancel).pack(side=tk.RIGHT)

        # 等待窗口渲染完成后获取尺寸并定位
        self.update_idletasks()

        # 计算并设置对话框位置（在主窗口中央）
        parent_x = parent.winfo_rootx()
        parent_y = parent.winfo_rooty()
        parent_width = parent.winfo_width()
        parent_height = parent.winfo_height()

        dialog_width = self.winfo_width()
        dialog_height = self.winfo_height()

        # 计算对话框位置使其居中显示
        x = parent_x + (parent_width - dialog_width) // 2
        y = parent_y + (parent_height - dialog_height) // 2

        self.geometry(f"+{x}+{y}")

    def on_ok(self):
        """确定按钮处理"""
        self.result = self.text_area.get("1.0", tk.END).strip()
        self.destroy()

    def on_cancel(self):
        """取消按钮处理"""
        self.result = None
        self.destroy()

    def show(self):
        """显示并等待结果"""
        self.wait_window(self)
        return self.result


def open_directory_fast(path):
    """快速打开目录资源管理器（不检查路径是否存在）"""
    try:
        # 直接使用系统调用打开资源管理器
        os.startfile(os.path.normpath(path))
        return True
    except Exception as e:
        print(e)
        return False


class HelpProj:
    def __init__(self, root):
        self.root = root
        self.root.title("HelpProj")
        self.root.configure(bg="white")

        # 存储结构：{页签名称: {命令名称: 命令内容}}
        self.categories = {}
        self.current_category = None
        self.current_command = None

        # 数据文件路径
        self.DATA_FILE = "command_data.json"
        self.CONFIG_FILE = "app_config.json"

        # 加载配置
        self.load_config()

        # 创建主界面
        self.create_widgets()

        # 加载数据
        self.load_data()

    def create_widgets(self):
        """创建界面元素"""
        # 主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 标题区域
        title_frame = ttk.Frame(main_frame)
        title_frame.pack(fill=tk.X, pady=(0, 5))

        # 页签管理区域
        notebook_frame = ttk.Frame(main_frame)
        notebook_frame.pack(fill=tk.X, pady=(0, 10))

        # 页签名称 + 管理按钮
        self.notebook = ttk.Notebook(notebook_frame)
        self.notebook.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.notebook.bind("<<NotebookTabChanged>>", self.on_tab_changed)

        btn_frame = ttk.Frame(notebook_frame)
        btn_frame.pack(side=tk.RIGHT, padx=(5, 0))

        ttk.Button(btn_frame, text="+", width=2,
                   command=self.add_category).pack(side=tk.LEFT, padx=(0, 2))
        ttk.Button(btn_frame, text="-", width=2,
                   command=self.delete_category).pack(side=tk.LEFT)

        # 命令列表区域 (左侧)
        list_frame = ttk.Frame(main_frame)
        list_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))

        # 命令列表容器
        list_container = ttk.LabelFrame(list_frame, text="列表")
        list_container.pack(fill=tk.BOTH, expand=True)

        # 使用Listbox替代Text控件，解决选择问题
        self.command_listbox = tk.Listbox(
            list_container,
            height=22,
            bg="white",
            fg="black",
            font=("Arial", 10),
            selectbackground="#e0e0e0",
            selectforeground="black"
        )
        self.command_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 命令选择事件
        self.command_listbox.bind("<<ListboxSelect>>", self.on_command_select)

        # 底部按钮区域 (图片底部的"新增"和"删除"按钮)
        button_frame = ttk.Frame(list_frame)
        button_frame.pack(fill=tk.X, pady=(5, 0))

        ttk.Button(button_frame, text="拷贝", command=self.copy_command).pack(
            side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))
        ttk.Button(button_frame, text="新增", command=self.add_command).pack(
            side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))
        ttk.Button(button_frame, text="删除", command=self.delete_command).pack(
            side=tk.LEFT, fill=tk.X, expand=True)

        # 命令详情区域 (右侧)
        detail_frame = ttk.Frame(main_frame)
        detail_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 顶部显示当前命令标签
        self.command_label = tk.Label(
            detail_frame, text="命令详情：", bg="white", fg="black", anchor="w")
        self.command_label.pack(fill=tk.X, pady=(0, 5))

        # 命令详情文本框
        self.command_text = ScrolledText(
            detail_frame,
            height=10,
            wrap=tk.WORD,
            bg="#f8f8f8",
            fg="black",
            font=("Arial", 10),
            padx=5,
            pady=5,
            state=tk.DISABLED
        )
        self.command_text.pack(fill=tk.BOTH)

        # 参数区域
        param_frame = ttk.LabelFrame(detail_frame, text="参数输入 ({0} {1} ...)")
        param_frame.pack(fill=tk.X, pady=(10, 0))

        self.param_text = ScrolledText(
            param_frame,
            height=4,
            wrap=tk.WORD,
            bg="white",
            fg="black",
            font=("Arial", 10),
            padx=5,
            pady=5
        )
        self.param_text.pack(fill=tk.BOTH)

        # 生成命令区域
        generate_frame = ttk.Frame(detail_frame)
        generate_frame.pack(fill=tk.BOTH, expand=True, pady=(10, 5))

        self.generate_text = ScrolledText(
            generate_frame,
            height=4,
            wrap=tk.WORD,
            bg="#f8f8f8",
            fg="black",
            font=("Arial", 10),
            padx=5,
            pady=5,
            state=tk.DISABLED
        )
        self.generate_text.pack(fill=tk.BOTH, expand=True)

        self.open_file_button = ttk.Button(generate_frame, text="打开目录", command=self.open_file_command)
        self.open_file_button.pack(side=tk.LEFT, fill=tk.X, expand=True, pady=(10, 0))
        self.open_file_button.config(state=tk.DISABLED)

        # 绑定关闭事件，保存配置
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def load_config(self):
        """加载应用配置"""
        # 设置默认配置
        self.config = {
            "geometry": "800x600",
            "selected_category": "default",
            "selected_command": ""
        }

        if os.path.exists(self.CONFIG_FILE):
            try:
                with open(self.CONFIG_FILE, 'r') as f:
                    loaded_config = json.load(f)
                    self.config.update(loaded_config)
            except:
                pass

        # 应用窗口配置
        self.root.geometry(self.config["geometry"])

    def save_config(self):
        """保存应用配置"""
        # 更新当前窗口位置
        self.config["geometry"] = self.root.geometry()

        # 更新当前选择的页签和命令
        self.config["selected_category"] = self.current_category if self.current_category else "default"
        self.config["selected_command"] = self.current_command if self.current_command else ""

        with open(self.CONFIG_FILE, 'w') as f:
            json.dump(self.config, f, indent=2)

    def load_data(self):
        """从文件加载数据"""
        if os.path.exists(self.DATA_FILE):
            try:
                with open(self.DATA_FILE, 'r') as f:
                    data = json.load(f)
                    self.categories = data.get("categories", {})

                    # 如果没有分类，添加默认分类
                    if not self.categories:
                        self.init_minimal_data()
                    else:
                        self.refresh_ui()
            except:
                self.init_minimal_data()
        else:
            self.init_minimal_data()

    def save_data(self):
        """保存数据到文件"""
        # 保存当前命令编辑内容
        if self.current_command and self.current_category:
            current_content = self.command_text.get("1.0", tk.END).strip()
            if current_content:
                self.categories[self.current_category][self.current_command] = current_content

        # 保存所有数据
        with open(self.DATA_FILE, 'w') as f:
            json.dump({
                "categories": self.categories
            }, f, indent=2)

    def init_minimal_data(self):
        """初始化最小示例数据"""
        self.categories = {
            "default": {}
        }
        self.refresh_ui()

    def refresh_ui(self):
        """刷新UI显示"""
        # 刷新页签
        for widget in self.notebook.winfo_children():
            widget.destroy()

        for category in self.categories:
            frame = ttk.Frame(self.notebook)
            self.notebook.add(frame, text=category)

        # 默认选中第一个页签
        if self.categories:
            # 尝试加载保存的页签
            saved_category = self.config.get("selected_category")
            if saved_category and saved_category in self.categories:
                self.notebook.select(
                    list(self.categories.keys()).index(saved_category))
                self.current_category = saved_category
            else:
                self.notebook.select(0)
                self.current_category = list(self.categories.keys())[0]

            self.refresh_command_list()

            # 尝试恢复保存的命令选择
            saved_command = self.config.get("selected_command")
            if saved_command and saved_command in self.categories[self.current_category]:
                self.select_command(saved_command)

    def refresh_command_list(self):
        """刷新命令列表显示"""
        self.command_listbox.delete(0, tk.END)

        if self.current_category:
            commands = self.categories[self.current_category]
            for cmd_name in commands:
                self.command_listbox.insert(tk.END, f"{cmd_name}")

        # 如果当前有选中的命令，突出显示
        if self.current_command:
            for i in range(self.command_listbox.size()):
                item = self.command_listbox.get(i)
                if f"复制 {self.current_command}" == item:
                    self.command_listbox.select_set(i)
                    self.command_listbox.see(i)
                    break

    def select_command(self, command_name):
        """选择指定命令"""
        if not self.current_category:
            return

        self.current_command = command_name
        cmd_content = self.categories[self.current_category][command_name]
        self.command_text.config(state=tk.NORMAL)
        self.command_text.delete(1.0, tk.END)
        self.command_text.insert(tk.END, cmd_content)
        self.command_text.config(state=tk.DISABLED)
        self.command_label.config(text=f"详情：{command_name}")
        self.save_config()  # 保存当前选择状态

    def on_tab_changed(self, event):
        """当切换页签时更新命令列表"""
        selected_tab = self.notebook.select()
        if selected_tab:
            tab_index = self.notebook.index(selected_tab)
            self.current_category = list(self.categories.keys())[tab_index]
            self.refresh_command_list()
            self.current_command = None
            self.command_text.config(state=tk.NORMAL)
            self.command_text.delete(1.0, tk.END)
            self.command_text.config(state=tk.DISABLED)
            self.command_label.config(text="详情：")
            self.save_config()  # 保存当前选择状态

    def add_category(self):
        """添加新页签"""
        name = simpledialog.askstring("新增页签", "请输入页签名称:")
        if not name:
            return

        if name in self.categories:
            messagebox.showerror("错误", f"页签 '{name}' 已存在")
            return

        self.categories[name] = {}
        self.save_data()
        self.refresh_ui()

        # 选中新页签
        self.current_category = name
        self.save_config()  # 保存当前选择状态

        # 刷新后自动选择新页签
        self.root.after(100, lambda: self.notebook.select(
            list(self.categories.keys()).index(name)))

    def delete_category(self):
        """删除当前页签"""
        if not self.current_category:
            return

        # 防止删除所有页签
        if len(self.categories) <= 1:
            messagebox.showwarning("删除", "至少需要保留一个页签")
            return

        if messagebox.askyesno("删除页签", f"确定要删除页签 '{self.current_category}' 吗?"):
            del self.categories[self.current_category]
            self.save_data()
            self.current_command = None

            # 选择前一个页签
            self.current_category = list(self.categories.keys())[0]
            self.refresh_ui()

            # 刷新后自动选择页签
            self.root.after(100, lambda: self.notebook.select(0))
            self.save_config()  # 保存当前选择状态

    def on_command_select(self, event):
        """当选择命令时显示命令详情"""
        if not self.current_category:
            return

        selected = self.command_listbox.curselection()
        if not selected:
            return

        # 获取选中的命令文本
        select_command = self.command_listbox.get(selected[0])
        if select_command in self.categories[self.current_category]:
            self.current_command = select_command
            cmd_content = self.categories[self.current_category][select_command]
            self.command_text.config(state=tk.NORMAL)
            self.command_text.delete(1.0, tk.END)
            self.command_text.insert(tk.END, cmd_content)
            self.command_text.config(state=tk.DISABLED)
            self.command_label.config(text=f"详情：{select_command}")
            self.save_config()  # 保存当前选择状态
            
            if os.path.exists(cmd_content) and os.path.isdir(cmd_content):
                self.open_file_button.config(state=tk.NORMAL)
            else:
                self.open_file_button.config(state=tk.DISABLED)

    def add_command(self):
        """添加新命令"""
        if not self.current_category:
            messagebox.showwarning("错误", "请先选择一个页签")
            return

        name = simpledialog.askstring("新增命令", "请输入命令名称:")
        if not name:
            return

        if name in self.categories[self.current_category]:
            messagebox.showerror("错误", f"命令 '{name}' 已存在")
            return

        content_dialog = LargeTextDialog(self.root, "新增命令", "请输入命令内容:")
        content = content_dialog.show()
        if not content:
            return

        self.categories[self.current_category][name] = content
        self.save_data()
        self.refresh_command_list()
        self.save_config()  # 保存当前状态

    def open_file_command(self):
        """执行当前选中的命令"""
        self.gen_command()

        # 获取命令
        path = self.generate_text.get(1.0, tk.END).strip()

        if open_directory_fast(path) == False:
            messagebox.showwarning("错误", f"无效的 Windows 路径: {path}")

    def delete_command(self):
        """删除当前选中的命令"""
        if not self.current_command:
            messagebox.showwarning("错误", "请先选择一个命令")
            return

        if messagebox.askyesno("删除命令", f"确定要删除命令 '{self.current_command}' 吗?"):
            del self.categories[self.current_category][self.current_command]
            self.current_command = None
            self.save_data()
            self.refresh_command_list()
            self.command_text.config(state=tk.NORMAL)
            self.command_text.delete(1.0, tk.END)
            self.command_text.config(state=tk.DISABLED)
            self.command_label.config(text="命令详情：")
            self.save_config()  # 保存当前状态

    def gen_command(self):
        """使用参数拷贝最终命令"""
        if not self.current_command:
            messagebox.showwarning("拷贝", "请先选择一个命令")
            return

        # 获取基础命令
        cmd = self.command_text.get(1.0, tk.END).strip()
        if not cmd:
            messagebox.showwarning("拷贝", "命令内容为空")
            return

        # 获取参数
        param_data = self.param_text.get(1.0, tk.END).strip()

        # 分割参数
        try:
            params = param_data.split()
            # 替换占位符 {0}, {1}, ...
            for i in range(len(params)):
                placeholder = "{" + str(i) + "}"
                if placeholder in cmd:
                    cmd = cmd.replace(placeholder, params[i])
        except Exception as e:
            messagebox.showerror("参数错误", f"参数处理失败: {str(e)}")
            return

        # 显示结果
        self.generate_text.config(state=tk.NORMAL)
        self.generate_text.delete(1.0, tk.END)
        self.generate_text.insert(tk.END, cmd)
        self.generate_text.config(state=tk.DISABLED)

    def copy_command(self):
        # 首先生成命令
        self.gen_command()

        # 获取命令
        cmd = self.generate_text.get(1.0, tk.END).strip()

        # 拷贝结果
        # 清空剪贴板并添加新内容
        self.root.clipboard_clear()
        self.root.clipboard_append(cmd)

        # 确保内容被复制 (对于某些系统可能需要update)
        self.root.update()

    def on_closing(self):
        """窗口关闭时保存所有配置和编辑内容"""
        self.save_config()
        self.save_data()
        self.root.destroy()


# 运行程序
if __name__ == "__main__":
    root = tk.Tk()
    app = HelpProj(root)
    root.mainloop()
